import 'dart:async';
import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hc_bot_pro/common/service/sdk_service.dart';
import 'package:hc_bot_pro/common/tool/datetime_ex.dart';
import 'package:hc_bot_pro/common/tool/string_ex.dart';

class ChatService {
  final path = "/cloud-digital-healing/sse/aiStream";
  final host = Get.find<SDKService>().host;

  CancelToken? _cancelToken = CancelToken();

  // callback
  Function(String)? onData;
  Function? onDone;
  Function? onCancelled;
  Function(dynamic)? onError;

  // 创建Dio实例
  final dio = Dio(
    BaseOptions(
      // 请求连接超时时间
      connectTimeout: const Duration(seconds: 20),
      // 因为是流式响应，同时ai的回复响应速度也较久，固响应超时时间设置长些，此处设置为180秒
      receiveTimeout: const Duration(seconds: 120),
      // 设置响应类型为流式响应
      responseType: ResponseType.stream,
    ),
  );

  String genenrateConversationId() {
    final uuid =
        "${Get.find<SDKService>().uuid}-${Get.find<SDKService>().channelCode}-${DateTime.now().formattedString}";
    return uuid.md5Desc();
  }

  Future answer({
    required String question,
    required String conversationID,
  }) async {
    try {
      final urlStr = "$host$path";
      final param = {"chatId": conversationID, "content": question};
      debugPrint(param.toString());

      _cancelToken = CancelToken();

      var asStream = await dio.get(
        urlStr,
        queryParameters: param,
        cancelToken: _cancelToken,
      );
      await processStreamResponse(asStream.data.stream);
    } catch (e) {
      debugPrint(e.toString());
      if (onError != null) {
        onError!(e);
      }
    } finally {}
  }

  void cancel() {
    _cancelToken?.cancel();
    if (onCancelled != null && _cancelToken != null) {
      onCancelled!();
    }
    _cancelToken = null;
  }
}

extension on ChatService {
  Future<void> processStreamResponse(Stream stream) async {
    // 用于每个阶段的对话结果

    // 处理流式响应
    await for (var data in stream) {
      // 将字节数据解码为字符串
      final bytes = data as List<int>;
      final decodedData = utf8.decode(bytes);

      String jsonStr = decodedData.replaceAll("data:", "").trim();
      if (jsonStr.isEmpty) {
        continue;
      }
      debugPrint(jsonStr);
      if (jsonStr == '[DONE]') {
        _cancelToken = null;
        onDone!();
        return;
      }

      try {
        // 解析 JSON 数据
        final json = jsonDecode(jsonStr);

        // 获取当前阶段的对话结果，根据qwen模型的对接文档，这里的content就是当前阶段的对话结果，finish_reason表示当前阶段是否结束
        final content = json['choices'][0]['delta']['content'] as String;
        final finishReason = json['choices'][0]['finish_reason'] ?? '';

        if (content.isNotEmpty) {
          // 将每次的 content 添加到缓冲区中
          // 输出对话结果
          debugPrint("onDone: $content");
          final trimmed = content.replaceFirst("\n", "");
          if (trimmed.isNotEmpty) onData!(content.toString());
        }
        if (finishReason == 'stop') {
          // 如果 finish_reason 为 stop，则输出完整的对话完成结果
          print(content.toString());
        }
      } catch (e) {
        print('Error parsing JSON: $e, ${jsonStr}');
        // 如果解析失败，可以尝试其他方式处理数据
        // 例如，检查是否有其他非标准前缀，并进行相应的处理
      }
    }
  }
}
